/*********************************************************************
* Instituto Superior Tecnico de Lisboa, Portugal
* Technical University of Lisbon, Portugal
* 
* Agentes Autonomos e Sistemas Multiagente
* Autonomous Agents and Multiagent Systems
* 
* 2005/2006
*********************************************************************/
/*********************************************************************
* File: sounds
*
* Sound-related functions. These are Hooks to let the Agent 'hear' otherwise 
* unnoticed things. Base code and idea came from killaruna/ParaBot [UNTESTED]
*********************************************************************/
#include "sounds.h"
#include <assert.h>
#include "../util/util.h"
#include "../agents/globals.h"
using namespace agents;

/**
* Called by the sound hooking code (in EMIT_SOUND).
* Enters the played sound into the array associated with the entity
**/
void soundAttachToThreat(edict_t *pEdict, const char *pszSample, float fVolume)
{
   if (FNullEnt(pEdict))
      return; // reliability check

   Vector vecPosition = pEdict->v.origin;
   if (vecPosition == g_vecZero)
      vecPosition = util::vecBModelOrigin(pEdict);

   int iIndex = ENTINDEX(pEdict) - 1;
   if (iIndex < 0 || iIndex >= gpGlobals->maxClients)
      iIndex = util::getNearestPlayerIndex(vecPosition);

   if (strncmp("player/bhit_flesh", pszSample, 17) == 0 ||
      strncmp("player/headshot", pszSample, 15) == 0)
   {
      // Hit/Fall sound?
      g_threatTab[iIndex].hearingDistance = 800.0 * fVolume;
      g_threatTab[iIndex].timeSoundLasting = gpGlobals->time + 0.5;
      g_threatTab[iIndex].soundPosition = vecPosition;
   }
   else if (strncmp("items/gunpickup", pszSample, 15) == 0) 
   {
      // Weapon pickup?
      g_threatTab[iIndex].hearingDistance = 800.0 * fVolume;
      g_threatTab[iIndex].timeSoundLasting = gpGlobals->time + 0.5;
      g_threatTab[iIndex].soundPosition = vecPosition;
   }
   else if (strncmp("weapons/zoom", pszSample, 12) == 0)
   {
      // Sniper zooming?
      g_threatTab[iIndex].hearingDistance = 500.0 * fVolume;
      g_threatTab[iIndex].timeSoundLasting = gpGlobals->time + 0.1;
      g_threatTab[iIndex].soundPosition = vecPosition;
   }
   else if (strncmp("items/9mmclip", pszSample, 13) == 0) 
   {
      // Ammo pickup?
      g_threatTab[iIndex].hearingDistance = 500.0 * fVolume;
      g_threatTab[iIndex].timeSoundLasting = gpGlobals->time + 0.1;
      g_threatTab[iIndex].soundPosition = vecPosition;
   }
   else if (strncmp("hostage/hos", pszSample, 11) == 0)
   {
      // CT used hostage?
      g_threatTab[iIndex].hearingDistance = 1024.0 * fVolume;
      g_threatTab[iIndex].timeSoundLasting = gpGlobals->time + 5.0;
      g_threatTab[iIndex].soundPosition = vecPosition;
   }
   else if (strncmp("debris/bustmetal", pszSample, 16) == 0 ||
      strncmp("debris/bustglass", pszSample, 16) == 0)
   {
      // Broke something?
      g_threatTab[iIndex].hearingDistance = 1024.0 * fVolume;
      g_threatTab[iIndex].timeSoundLasting = gpGlobals->time + 2.0;
      g_threatTab[iIndex].soundPosition = vecPosition;
   }
   else if (strncmp("doors/doormove", pszSample, 14) == 0)
   {
      // Someone opened a door
      g_threatTab[iIndex].hearingDistance = 1024.0 * fVolume;
      g_threatTab[iIndex].timeSoundLasting = gpGlobals->time + 3.0;
      g_threatTab[iIndex].soundPosition = vecPosition;
   }
}


/**
* Tries to simulate playing of sounds to let the agents hear
* sounds which aren't captured through server sound hooking
**/
void soundSimulateUpdate(int iPlayerIndex)
{
   assert(iPlayerIndex >= 0);
   assert(iPlayerIndex < gpGlobals->maxClients);
   if (iPlayerIndex < 0 || iPlayerIndex >= gpGlobals->maxClients)
      return; // reliability check

   edict_t *pPlayer = g_threatTab[iPlayerIndex].pEdict;
   float fVelocity = pPlayer->v.velocity.Length2D();
   float fHearDistance = 0.0;
   float fTimeSound = 0.0;

   if (pPlayer->v.oldbuttons & IN_ATTACK) // Pressed attack button?
   {
      fHearDistance = 4096.0;
      fTimeSound = gpGlobals->time + 0.5;
   }
   else if (pPlayer->v.oldbuttons & IN_USE) // Pressed used button?
   {
      fHearDistance = 1024.0;
      fTimeSound = gpGlobals->time + 0.5;
   }
   else if (pPlayer->v.movetype == MOVETYPE_FLY) // Uses ladder?
   {
      if (abs(pPlayer->v.velocity.z) > 50)
      {
         fHearDistance = 1024.0;
         fTimeSound = gpGlobals->time + 0.3;
      }
   }
   else
   {
      // Moves fast enough?
      fHearDistance = 1024.0 * (fVelocity / 260);
      fTimeSound = gpGlobals->time + 0.3;
   }

   if (fHearDistance > 0.0) // Did issue sound?
   {
      // Some sound already associated?
      if (g_threatTab[iPlayerIndex].timeSoundLasting > gpGlobals->time)
      {
         // New Sound louder (bigger range) than old sound?
         if(g_threatTab[iPlayerIndex].hearingDistance <= fHearDistance)
         {
            // Override it with new
            g_threatTab[iPlayerIndex].hearingDistance = fHearDistance;
            g_threatTab[iPlayerIndex].timeSoundLasting = fTimeSound;
            g_threatTab[iPlayerIndex].soundPosition = pPlayer->v.origin;
         }
      }
      else // New sound?
      {
         // Just remember it
         g_threatTab[iPlayerIndex].hearingDistance = fHearDistance;
         g_threatTab[iPlayerIndex].timeSoundLasting = fTimeSound;
         g_threatTab[iPlayerIndex].soundPosition = pPlayer->v.origin;
      }
   }
}
